1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.util.concurrent;
18
19 import junit.framework.TestCase;
20
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.Executors;
24 import java.util.concurrent.TimeUnit;
25
26
27
28
29
30
31 public class SimpleTimeLimiterTest extends TestCase {
32
33 private static final int DELAY_MS = 50;
34 private static final int ENOUGH_MS = 500;
35 private static final int NOT_ENOUGH_MS = 5;
36
37 private TimeLimiter service;
38
39 private static final ExecutorService executor
40 = Executors.newFixedThreadPool(1);
41
42 private static String someGoodStaticMethod() throws InterruptedException {
43 TimeUnit.MILLISECONDS.sleep(DELAY_MS);
44 return "yes";
45 }
46
47 private static String someBadStaticMethod() throws InterruptedException,
48 SampleException {
49 TimeUnit.MILLISECONDS.sleep(DELAY_MS);
50 throw new SampleException();
51 }
52
53 @Override protected void setUp() throws Exception {
54 super.setUp();
55 service = new SimpleTimeLimiter(executor);
56 }
57
58 public void testGoodCallableWithEnoughTime() throws Exception {
59 long start = System.nanoTime();
60 String result = service.callWithTimeout(
61 new Callable<String>() {
62 @Override
63 public String call() throws InterruptedException {
64 return someGoodStaticMethod();
65 }
66 }, ENOUGH_MS, TimeUnit.MILLISECONDS, true);
67 assertEquals("yes", result);
68 assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
69 }
70
71 public void testGoodCallableWithNotEnoughTime() throws Exception {
72 long start = System.nanoTime();
73 try {
74 service.callWithTimeout(
75 new Callable<String>() {
76 @Override
77 public String call() throws InterruptedException {
78 return someGoodStaticMethod();
79 }
80 }, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS, true);
81 fail("no exception thrown");
82 } catch (UncheckedTimeoutException expected) {
83 }
84 assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
85 }
86
87 public void testBadCallableWithEnoughTime() throws Exception {
88 long start = System.nanoTime();
89 try {
90 service.callWithTimeout(
91 new Callable<String>() {
92 @Override
93 public String call() throws SampleException, InterruptedException {
94 return someBadStaticMethod();
95 }
96 }, ENOUGH_MS, TimeUnit.MILLISECONDS, true);
97 fail("no exception thrown");
98 } catch (SampleException expected) {
99 }
100 assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
101 }
102
103 public void testBadCallableWithNotEnoughTime() throws Exception {
104 long start = System.nanoTime();
105 try {
106 service.callWithTimeout(
107 new Callable<String>() {
108 @Override
109 public String call() throws SampleException, InterruptedException {
110 return someBadStaticMethod();
111 }
112 }, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS, true);
113 fail("no exception thrown");
114 } catch (UncheckedTimeoutException expected) {
115 }
116 assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
117 }
118
119 public void testGoodMethodWithEnoughTime() throws Exception {
120 SampleImpl target = new SampleImpl();
121 Sample proxy = service.newProxy(
122 target, Sample.class, ENOUGH_MS, TimeUnit.MILLISECONDS);
123 long start = System.nanoTime();
124 assertEquals("x", proxy.sleepThenReturnInput("x"));
125 assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
126 assertTrue(target.finished);
127 }
128
129 public void testGoodMethodWithNotEnoughTime() throws Exception {
130 SampleImpl target = new SampleImpl();
131 Sample proxy = service.newProxy(
132 target, Sample.class, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS);
133 long start = System.nanoTime();
134 try {
135 proxy.sleepThenReturnInput("x");
136 fail("no exception thrown");
137 } catch (UncheckedTimeoutException expected) {
138 }
139 assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
140
141
142 assertFalse(target.finished);
143 TimeUnit.MILLISECONDS.sleep(ENOUGH_MS);
144 assertFalse(target.finished);
145 }
146
147 public void testBadMethodWithEnoughTime() throws Exception {
148 SampleImpl target = new SampleImpl();
149 Sample proxy = service.newProxy(
150 target, Sample.class, ENOUGH_MS, TimeUnit.MILLISECONDS);
151 long start = System.nanoTime();
152 try {
153 proxy.sleepThenThrowException();
154 fail("no exception thrown");
155 } catch (SampleException expected) {
156 }
157 assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
158 }
159
160 public void testBadMethodWithNotEnoughTime() throws Exception {
161 SampleImpl target = new SampleImpl();
162 Sample proxy = service.newProxy(
163 target, Sample.class, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS);
164 long start = System.nanoTime();
165 try {
166 proxy.sleepThenThrowException();
167 fail("no exception thrown");
168 } catch (UncheckedTimeoutException expected) {
169 }
170 assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
171 }
172
173 private static void assertTheCallTookBetween(
174 long startNanos, int atLeastMillis, int atMostMillis) {
175 long nanos = System.nanoTime() - startNanos;
176 assertTrue(nanos >= atLeastMillis * 1000000);
177 assertTrue(nanos <= atMostMillis * 1000000);
178 }
179
180 public interface Sample {
181 String sleepThenReturnInput(String input);
182 void sleepThenThrowException() throws SampleException;
183 }
184
185 @SuppressWarnings("serial")
186 public static class SampleException extends Exception {}
187
188 public static class SampleImpl implements Sample {
189 boolean finished;
190
191 @Override
192 public String sleepThenReturnInput(String input) {
193 try {
194 TimeUnit.MILLISECONDS.sleep(DELAY_MS);
195 finished = true;
196 return input;
197 } catch (InterruptedException e) {
198 return null;
199 }
200 }
201 @Override
202 public void sleepThenThrowException() throws SampleException {
203 try {
204 TimeUnit.MILLISECONDS.sleep(DELAY_MS);
205 } catch (InterruptedException e) {
206 }
207 throw new SampleException();
208 }
209 }
210 }